<template>
    <div class="chart-wrapper">
        <div id="chart" ref="chartContainer"></div>
    </div>
</template>

<script setup lang="ts" name="RingChartV2">
    import { ref, onMounted, onBeforeUnmount, onUnmounted, watch, computed, reactive } from 'vue';
    import * as echarts from 'echarts';
    import {filterLabel, filterEmphasis} from '@/common/util'


    let chart: echarts.ECharts | null = null; // 声明图表实例
    const chartContainer = ref(null);
    const highlightState = reactive({
        type: '', // 'Start' 或 'End'
        value: null // 对应的 start/end 值
    })


    const props = defineProps(['innerData', 'outerData', 'middleData', 'globalStart', 'globalEnd', 'totalInner', 'totalMid'])

    function getChromRing() {
        const separatorTemplate = {
            name: 'sep',
            value: props.totalInner * 0.003,               // 线的粗细，越小越细
            itemStyle: { color: '#000' },
            label: { show: false },
            labelLine: { show: false }
        };

        // 用 forEach 或 flatMap，把真实数据和分隔项交错拼进去
        const dataWithSeps = props.innerData.flatMap((item:any, idx:any) => {
            return [
                item,
                // 这里要深拷贝一份模板，否则每个 sep 都指向同一个对象，后面修改会互相影响
                { ...separatorTemplate }
            ];
        });

        return {
            name: 'middle',
            type: 'pie',
            radius: ['40%', '50%'],
            center: ['50%', '50%'],
            avoidLabelOverlap: true,
            label: {
                show: true,
                position: 'inside',
                rotate: 'tangential',
            },
            labelLine: {
                show: false
            },
            emphasis: {
                label: {
                    show: true,
                    // position: 'inside',
                    // overflow: "break",
                    formatter: (params: any) => {
                        return `{name|${params.data.name}}\n{-${params.data.end}}`;
                    },
                    rich: {
                        name: {
                            fontSize: 12,
                            color: 'black',
                            align: 'center',
                            z:  10
                        },
                        range: {
                            fontSize: 10,
                            color: 'black',
                            align: 'center',
                            padding: [10, 0, 0, 0]
                        }
                    }
                }
            },
            data: dataWithSeps
        }
    }

    // 将一个数值映射到 [0,360] 的角度
    function toAngle(x: number) {
        return ((x - props.globalStart) / (props.globalEnd - props.globalStart)) * 360
    }


    function getCNRing() {
        const base = 80; // 基准半径
        const amp = 20;  // 振幅
        const allCNs = props.outerData.flatMap((seg:any) => seg.cnList);
        const maxCN = Math.max(...allCNs, 1); // 防止除零

        return props.outerData.map((seg: any, idx: number) => {
            const cnList = seg.cnList;
            const maxIdx = cnList.indexOf(Math.max(...cnList));
            const minIdx = cnList.indexOf(Math.min(...cnList));

            const data = cnList.map((cn: any, i: number) => {
            const globalPos = seg.coordList[i];
            const angle = toAngle(globalPos);
            const r = base + (cn / maxCN) * amp;

            return {
                value: [r, angle],
                label: {
                    show: props.outerData.length <= 5 && (i === maxIdx || i === minIdx),
                    position: 'outside',
                    distance: 10,
                    formatter: i === maxIdx
                    ? `CN Max: ${cn.toFixed(2)}`
                    : i === minIdx
                        ? `CN Min: ${cn.toFixed(2)}`
                        : '',
                    fontSize: 12,
                    color: '#333'
                    }
                };
            });

            // baseData，顺序反过来拼接，形成封闭路径
            const baseData = seg.coordList.map((globalPos: any) => {
            const angle = toAngle(globalPos);
            return [base, angle];
            }).reverse();

            const polygonData = [...data, ...baseData];

            return {
                name: seg.name || `Outer ${idx + 1}`,
                type: 'line',
                coordinateSystem: 'polar',
                data: polygonData,
                showSymbol: true, // 必须 true，label 才能显示
                symbol: 'dot',    // 👈 不显示拐点
                symbolSize: 0.1,
                lineStyle: {
                    width: 2,
                    color: seg.color || '#5470c6'
                },
                areaStyle: {
                    color: seg.color || '#5470c6',
                    opacity: 1
                },
                smooth: true
            };
        });
    }

    function getGeneRing() {
        return {
            name: 'geneRing',
            type: 'custom',
            coordinateSystem: 'polar',
            // 只需要一个 data 占位，renderItem 里自己循环 middleData
            data: [{}],
            renderItem(params: any, api: any) {
                const coordSys = params.coordSys;
                const cx = coordSys.cx;
                const cy = coordSys.cy;
                // 计算中圈的像素半径区间（可按需调整比例）
                // 我们在两者中点做弧线
                const radius = Math.min(api.getWidth(), api.getHeight()) / 2 * 0.4 * 0.56

                const children: any[] = [];

                props.middleData.forEach((item: any) => {
                    // 跳过空白或透明段
                    if (!item.name || (item.itemStyle && item.itemStyle.opacity === 0)) {
                        return;
                    }
                    // 1. 角度映射：将染色体坐标或 renderStart/renderEnd 映射到 0–360°
                    const angleStart = ((item.renderStart - props.globalStart) / props.totalMid) * 360;
                    const angleEnd   = ((item.renderEnd   - props.globalStart) / props.totalMid) * 360;

                    // 2. 计算起点、终点的像素坐标
                    const startPoint = api.coord([ radius, angleStart ]);
                    const endPoint   = api.coord([ radius, angleEnd]);

                    // 3. 计算像素半径（起点到中心的距离）
                    const dx     = startPoint[0] - cx;
                    const dy     = startPoint[1] - cy;
                    const rPixel = Math.sqrt(dx * dx + dy * dy);

                    // 4. 计算 SVG 弧度参数
                    const startRad = angleStart * Math.PI / 180;
                    const endRad   = angleEnd   * Math.PI / 180;
                    const delta    = endRad - startRad;
                    const largeArc  = Math.abs(delta) > Math.PI ? 1 : 0;
                    const sweepFlag = delta > 0 ? 1 : 0;

                    const isHighlighted = 
                        highlightState.type === 'Path' && 
                        highlightState.value === item.name;

                    // 6. 把 path 命令拼成字符串
                    const d = [
                        `M${startPoint[0]},${startPoint[1]}`,
                        `A${rPixel},${rPixel},0,${largeArc},${sweepFlag},${endPoint[0]},${endPoint[1]}`
                    ].join(' ');

                    // 5. 推入弧线和端点
                    children.push(
                        {
                            type: 'path',
                            shape: { d },          // 用字符串，不要数组
                            style: {
                                stroke: '#f00',
                                lineWidth: 2,
                                fill: 'none'
                            },
                            textContent: {
                                type: 'text',
                                style: {
                                    text: `${item.name}`,
                                    fill: '#000',
                                    font: '12px sans-serif',
                                }
                            },
                            textConfig: {
                                position: 'inside',
                            },
                            emphasis: { 
                                style: { 
                                    stroke: 'red', 
                                    lineWidth: 3 
                                },
                            },
                            info: {
                                name: item.name,
                                type: 'Path',
                                value: item.start
                            },
                            z2: 99
                        },
                        {
                            type: 'circle',
                            shape: { cx: startPoint[0], cy: startPoint[1], r: 3 },
                            style: { fill: '#f00' },
                            textContent: {
                                type: 'text',
                                style: {
                                    text: `${item.start}`,
                                    fill: '#000',
                                    font: '12px sans-serif',
                                    opacity: isHighlighted ? 1 : 0
                                }
                            },
                            textConfig: {
                                position: "inside",
                            },
                            info: {
                                name: item.name,
                                type: 'Start',
                                value: item.start
                            },
                        },
                        {
                            type: 'circle',
                            shape: { cx: endPoint[0],   cy: endPoint[1],   r: 3 },
                            style: { fill: '#f00' },
                            textContent: {
                                type: 'text',
                                style: {
                                    text: `${item.end}`,
                                    fill: '#000',
                                    font: '12px sans-serif',
                                    opacity: isHighlighted ? 1 : 0
                                }
                            },
                            textConfig: {
                                position: "inside",
                            },
                            info: {
                                name: item.name,
                                type: 'End',
                                value: item.end
                            },
                        }
                    );
                });

                return {
                    type: 'group',
                    children
                };
            }
        };
        }


    const updateChart = () => {
        if (!chart) return;
        let option = ref({
            polar: {
                radius: ['0%', '100%'],
            },
            angleAxis: {
                type: 'value',
                startAngle: 90,
                clockwise: true,
                min: 0,
                max: 360,
                show: false,
            },
            radiusAxis: {
                type: 'value',
                min: 0,
                max: 100,
                show: false,
            },
            series: [
                getChromRing(),
                getGeneRing(),
                ...getCNRing(),
            ]
        })
        chart.setOption(option.value); // 更新图表的配置
    };

    watch([() => props.innerData, () => props.outerData, () => props.middleData,], updateChart, { deep: true });

    // 监听高亮状态变化
    watch(highlightState, () => {
        updateChart()
    })

    onMounted(() => {
        chart = echarts.init(chartContainer.value); // 初始化图表
        updateChart(); // 初始化时设置图表的配置

        chart.on('mouseover', function (params: any) {
            if (params.componentSubType === 'custom' && params.info) {
                highlightState.type = params.info.type
                highlightState.value = params.info.name
            }
        })

        chart.on('mouseout', () => {
            highlightState.type = ''
            highlightState.value = null
        })
    });



    onUnmounted(() => {
        if (chart) {
            chart.dispose()
            chart = null
        }
    })
</script>

<style scoped>
    .chart-wrapper {
        display: flex;
        justify-content: center;
        align-items: center;
        width: 100%; /* 让容器占满 */
        height: 80vh; /* 或者指定高度 */
    }

    #chart {
        width: 100%;
        height: 600px;
    }
</style>
